//
//  YWDownloadDataTaskTool.m
//  videoTest3
//
//  Created by jun peng on 2022/8/15.
//

#import "YWDownloadDataTaskTool.h"

@interface YWDownloadDataTaskTool ()<NSURLSessionDataDelegate>

//由status里面属性fullPath产生、不需要保存到本地
@property (nonatomic, strong) NSFileHandle *handle;

//当你进入下载页面、传入status进来我就创建一个由新的session创建一个新的任务
@property (nonatomic, strong)  NSURLSessionDataTask *dataTask;

/* AFURLSessionManager */
@property (nonatomic, strong) AFURLSessionManager *manager;

@end

@implementation YWDownloadDataTaskTool

- (AFURLSessionManager *)manager {

    if (!_manager) {
        NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
        
//设置超时时间、这样大概率长时间不会超时导致下载失败、弄大一点时间、不能用MAXFloat
//不对、好像不设置超时、就算超时下载失败、只要正常关闭app再打开不是马上运行Xcode的话、我依然可以当暂停处理依然可以继续下载、进度条不会从0开始、也可以删除视频（fullPath没有改变）、当然你这里也可以设置超时、这样3000.0秒内都不会超时
        configuration.timeoutIntervalForRequest = 3000.0;
        configuration.timeoutIntervalForResource = 3000.0;
        
        // 1. 创建会话管理者
        _manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
        
        AFHTTPResponseSerializer *serializer = [AFHTTPResponseSerializer serializer];
        
        serializer.acceptableContentTypes = [NSSet setWithObjects:@"video/mp4",nil];
        
        _manager.responseSerializer = serializer;
        
        
    }
    return _manager;
}

- (NSURLSessionDataTask *)dataTask {

    if (_dataTask == nil) {
        
        NSURL *url = [NSURL URLWithString:self.status.VideoUrl];
          
        //2.创建请求对象
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

        YWLog(@"self.status.fullPath：%@",self.status.fullPath);
        
        self.status.currentSize = [self getFileSizeWithFullPath:self.status.fullPath];

        //3 设置请求头信息,告诉服务器请求那一部分数据
        NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.status.currentSize];
        [request setValue:range forHTTPHeaderField:@"Range"];
        
        MJWeakSelf

#pragma mark - //“完成”之后要做的事
        _dataTask = [self.manager dataTaskWithRequest:request completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {

                //关闭文件句柄
                [weakSelf.handle closeFile];
                weakSelf.handle = nil;
                
//                YWLog(@"%@",error);
                
                if (error == nil) {
                    
                    //1、改枚举状态
                    weakSelf.status.downloadType = YWDownloadType_Finish3;
                    
                    //2、数据库
                    //移除正在中的数据库、再添加到完成了的数据库
                    [YWDownloadDataBaseTool removeDownloadingStatus:weakSelf.status];
                    [YWDownloadDataBaseTool addFinishStatus:weakSelf.status];
                    
                    //回到主线程
                    dispatch_async(dispatch_get_main_queue(), ^{
                      
                    //3、发送通知
                        NSDictionary *userInfo = @{YWDownloadStatusKey:weakSelf.status};
                        [[NSNotificationCenter defaultCenter] postNotificationName:YWFinishDownloadNote object:weakSelf userInfo:userInfo];
                    });
                    
                }
                else{
                    
                    YWLog(@"error.code:%ld",error.code);
                    YWLog(@"error.domain:%@",error.domain);
                    YWLog(@"error.userInfo:%@",error.userInfo);
                    YWLog(@"error.userInfo.description:%@",error.userInfo.description);
                    YWLog(@"error.userInfo.keyValues.count:%ld",error.userInfo.keyValues.count);
                    YWLog(@"error.dataTask.state:%ld",weakSelf.dataTask.state);
                    
                    if (error.code == -1001) { //超时处理
                        YWLog(@"%@",error);
                        //置空、假如要继续下载的话就会让它重新发起新的下载请求
                        weakSelf.dataTask = nil;
                        //return就是让数据库让它依然保持“暂停”状态、（虽然其实是超时的error但是可以给用户一个假象）
                        return;
                    }

                    //删除任务后仍然会走这个回调、所以增加这个判断
                    if (weakSelf == nil) {
                        return;
                    }
                    
                    //1、改枚举状态
                    weakSelf.status.downloadType = YWDownloadType_Error3;
                    
                    //2、数据库
                    //更新正在中的数据库
                    [YWDownloadDataBaseTool updateDownloadingStatus:weakSelf.status];
                    
                    //回到主线程
                    dispatch_async(dispatch_get_main_queue(), ^{
                        
                        //删除任务后仍然会走这个回调、所以增加这个判断
                        if (weakSelf == nil) {
                            return;
                        }
                        
                        //3、发送通知
                        NSDictionary *userInfo = @{YWDownloadStatusKey:weakSelf.status};
                        [[NSNotificationCenter defaultCenter] postNotificationName:YWErrorDownloadNote object:weakSelf userInfo:userInfo];
                    });
                }

        }];

#pragma mark - //收到服务器的“响应”的block
        [self.manager setDataTaskDidReceiveResponseBlock:^NSURLSessionResponseDisposition(NSURLSession * _Nonnull session, NSURLSessionDataTask * _Nonnull dataTask, NSURLResponse * _Nonnull response) {
            
                NSURL *url = response.URL;
                NSLog(@"url:%@",url);
                
                //1、获得文件的总大小
                //expectedContentLength 本次请求的数据大小
                //这里设置totalSize、currentSize在发起开启下载的时候已经设置过这里不需要重复设置了
                weakSelf.status.totalSize = response.expectedContentLength + weakSelf.status.currentSize;
               
                //2、假如currentSize是零即一点数据根本不存在都没有就要创建一个文件了
                if (weakSelf.status.currentSize == 0) {
                    //创建空的文件
                    [[NSFileManager defaultManager]createFileAtPath:weakSelf.status.fullPath contents:nil attributes:nil];
                }
                
                //3、创建文件句柄
                weakSelf.handle = [NSFileHandle fileHandleForWritingAtPath:weakSelf.status.fullPath];
                
                //4、移动指针
                [weakSelf.handle seekToEndOfFile];
                
                //枚举
                weakSelf.status.downloadType = YWDownloadType_Downloading3;
                
                //5、数据库
                //更新正在中的数据库
                [YWDownloadDataBaseTool updateDownloadingStatus:weakSelf.status];
                
            return NSURLSessionResponseAllow;
        }];

        
#pragma mark - //收到服务器返回的“数据”的block
        [self.manager setDataTaskDidReceiveDataBlock:^(NSURLSession * _Nonnull session, NSURLSessionDataTask * _Nonnull dataTask, NSData * _Nonnull data) {
            
            //删除任务后仍然会走这个回调、所以增加这个判断
            if (weakSelf == nil) {
                return;
            }
            
                //1、写入数据到文件
                [weakSelf.handle writeData:data];
                
//                YWLog(@"data.length:%ld",data.length);
                
                //2、计算文件的下载进度
                weakSelf.status.currentSize += data.length; //不用这个、用这个根据fullPath获取更合理更准确
    //            weakSelf.status.currentSize = [weakSelf getFileSizeWithFullPath:weakSelf.status.fullPath];
                
                NSLog(@"progress:%f",1.0 * weakSelf.status.currentSize / weakSelf.status.totalSize);
                
                //3、数据库
                //更新正在中的数据库
                [YWDownloadDataBaseTool updateDownloadingStatus:weakSelf.status];
            
            //回到主线程
            dispatch_async(dispatch_get_main_queue(), ^{
                
                //删除任务后仍然会走这个回调、所以增加这个判断
                if (weakSelf == nil) {
                    return;
                }
                
                //发送通知给cell
                NSDictionary *userInfo = @{YWVideoUrlKey:weakSelf.status.VideoUrl,YWProgressKey:@(1.0 * weakSelf.status.currentSize / weakSelf.status.totalSize)};
                [[NSNotificationCenter defaultCenter] postNotificationName:YWDownloadRefreshListNote object:weakSelf userInfo:userInfo];
            });
            
        }];

    }

    return _dataTask;

}


//---//---//---//---//---//---//---//---//---//---//---//---//---//---//---//---//---//---//---//---//------//---//---//---//---//


-(void)setStatus:(YWDownloadStatus3 *)status{
    
    //设置首次开始下载的时间
    if (status.joinDownloadDate == nil) {
        
        status.joinDownloadDate = [YWDownloadStatus3 dateToString:[NSDate date]];
    }
       
    _status = status;
    
}


//将create和continue合并成一个方法，开启/继续一个任务
-(void)resumeDataTask{
    
    [self.dataTask resume];
    
}

//暂停一个任务
-(void)pauseDataTask{
    
    [self.dataTask suspend];
    
    YWLog(@"self.dataTask.state: %ld",self.dataTask.state);
    
}

//删除了一个任务
-(void)removeDataTask{
    
    
    //关闭文件句柄
//    [self.handle closeFile];
//    self.handle = nil;
    
    
    [self.dataTask cancel];
    self.dataTask = nil;
    
    //移除文件
    NSError *error2 = nil;
    if ([[NSFileManager defaultManager] fileExistsAtPath:self.status.fullPath]) {
         [[NSFileManager defaultManager] removeItemAtPath:self.status.fullPath error:&error2];
        if (error2 == nil) {
            YWLog(@"移除无效视频文件成功");
        }
        else{
            YWLog(@"移除无效视频文件失败");
        }
    }

}


//---//---//---//---//---//---//---//---//---//---//---//---//---//---//---//---//---//---//---//---//------//---//---//---//---//


-(void)dealloc
{
    //清理工作
    //finishTasksAndInvalidate
    [self.manager invalidateSessionCancelingTasks:YES];
}

//传入本地路径获取文件大小
-(NSInteger)getFileSizeWithFullPath:(NSString *)fullPath{
    
    //获得指定文件路径对应文件的数据大小
    NSDictionary *fileInfoDict = [[NSFileManager defaultManager]attributesOfItemAtPath:fullPath error:nil];
    
    NSLog(@"fullPath: %@",fullPath);
    
    NSLog(@"%@",fileInfoDict);
    NSInteger currentSize = [fileInfoDict[@"NSFileSize"] integerValue];
    
    return currentSize;
}
@end
